package com.sixj.keycloakssointegration.controller;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.*;

import javax.net.ssl.SSLContext;

@RestController
@RequestMapping("/api/sso")
public class ImpersonateController {

    static final String KEYCLOAK_BASE_URL = "https://192.168.173.171";
    static final String REALM = "runlion";
    static final String ADMIN_USERNAME = "admin";
    static final String ADMIN_PASSWORD = "admin";
    static final String CLIENT_ID = "admin-cli";

    @GetMapping("/impersonate")
    public String impersonate(@RequestParam String empNo) throws Exception {
        String token = getAdminToken();
        String userId = getUserIdByEmpNo(token, empNo);
        if (userId == null) {
            throw new RuntimeException("未找到该员工编号对应的用户：" + empNo);
        }
        String impersonateUrl = impersonateUser(token, userId);
        return impersonateUrl;
    }

    // 获取管理员token
    private static String getAdminToken() throws Exception {
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build();
        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
        HttpPost post = new HttpPost(KEYCLOAK_BASE_URL + "/realms/master/protocol/openid-connect/token");
        String body = "client_id=" + CLIENT_ID +
                "&username=" + ADMIN_USERNAME +
                "&password=" + ADMIN_PASSWORD +
                "&grant_type=password";
        post.setHeader("Content-Type", "application/x-www-form-urlencoded");
        post.setEntity(new StringEntity(body));
        String response = EntityUtils.toString(client.execute(post).getEntity());
        JsonNode node = new ObjectMapper().readTree(response);
        return node.get("access_token").asText();
    }

    // 根据工号查Keycloak userId
    private static String getUserIdByEmpNo(String token, String empNo) throws Exception {
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build();
        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
        String url = KEYCLOAK_BASE_URL + "/admin/realms/" + REALM + "/users?username=" + empNo;
        HttpGet get = new HttpGet(url);
        get.setHeader("Authorization", "Bearer " + token);
        CloseableHttpResponse response = client.execute(get);

        int status = response.getStatusLine().getStatusCode();
        if (status != 200) {
            throw new RuntimeException("查询用户失败，状态码: " + status);
        }
        String respBody = EntityUtils.toString(response.getEntity());
        JsonNode arr = new ObjectMapper().readTree(respBody);
        if (arr.isArray() && arr.size() > 0) {
            return arr.get(0).get("id").asText();
        }
        return null;
    }

    // 调用impersonation API
    private static String impersonateUser(String token, String userId) throws Exception {
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build();
        CloseableHttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
        HttpPost post = new HttpPost(KEYCLOAK_BASE_URL + "/admin/realms/" + REALM + "/users/" + userId + "/impersonation");
        post.setHeader("Authorization", "Bearer " + token);

        CloseableHttpResponse response = client.execute(post);
        int status = response.getStatusLine().getStatusCode();
        if (status != 200 && status != 201) {
            throw new RuntimeException("Impersonation failed, status: " + status);
        }
        String responseBody = EntityUtils.toString(response.getEntity());
        JsonNode node = new ObjectMapper().readTree(responseBody);
        return node.get("redirect").asText();
    }
}